﻿Imports System.Net
Imports Newtonsoft.Json
Imports BeatportNet.Catalog.Search

''' <summary>
''' The Beatport API object used for querying the Beatport database.
''' </summary>
''' <remarks></remarks>
Public Class Beatport
#Region "Constants"
    Friend Const BASE_URL As String = "http://api.beatport.com"

#Region "Cart"
    Friend Const CART_BASE_URL As String = BASE_URL & "/cart/1/"
#End Region

#Region "Catalog"
    Friend Const CATALOG_BASE_URL As String = BASE_URL & "/catalog/3"

    Friend Const CATALOG_ACCOUNT_TYPES_URL As String = CATALOG_BASE_URL & "/account-types"
    Friend Const CATALOG_ARTISTS_URL As String = CATALOG_BASE_URL & "/artists"
    Friend Const CATALOG_AUDIO_FORMATS_URL As String = CATALOG_BASE_URL & "/audio-formats"
    Friend Const CATALOG_AUTOCOMPLETE_URL As String = CATALOG_BASE_URL & "/autocomplete"
    Friend Const CATALOG_SEARCH_URL As String = CATALOG_BASE_URL & "/search"
    Friend Const CATALOG_CHARTS_URL As String = CATALOG_BASE_URL & "/charts"
    Friend Const CATALOG_COUNTRIES_URL As String = CATALOG_BASE_URL & "/countries"
    Friend Const CATALOG_CURRENCIES_URL As String = CATALOG_BASE_URL & "/currencies"
    Friend Const CATALOG_GENRES_URL As String = CATALOG_BASE_URL & "/genres"
    Friend Const CATALOG_ITEM_TYPES_URL As String = CATALOG_BASE_URL & "/item-types"
    Friend Const CATALOG_LABELS_URL As String = CATALOG_BASE_URL & "/labels"
    Friend Const CATALOG_MIXED_URL As String = CATALOG_BASE_URL & "/mixed"
    Friend Const CATALOG_RELEASES_URL As String = CATALOG_BASE_URL & "/releases"
    Friend Const CATALOG_SOURCE_TYPES_URL As String = CATALOG_BASE_URL & "/source-types"
    Friend Const CATALOG_TRACKS_URL As String = CATALOG_BASE_URL & "/tracks"
    Friend Const CATALOG_TRACK_SIMILAR_URL As String = CATALOG_BASE_URL & "/tracks/similar"

#Region "Beatport Detail Pages"
    Friend Const CATALOG_DETAIL_URL As String = CATALOG_BASE_URL & "/beatport"
    Friend Const CATALOG_DETAIL_HOME_URL As String = CATALOG_DETAIL_URL & "/home"
    Friend Const CATALOG_DETAIL_GENRE_URL As String = CATALOG_DETAIL_URL & "/genre"
    Friend Const CATALOG_DETAIL_LABEL_URL As String = CATALOG_DETAIL_URL & "/label"
    Friend Const CATALOG_DETAIL_ARTIST_URL As String = CATALOG_DETAIL_URL & "/artist"
    Friend Const CATALOG_DETAIL_CHART_URL As String = CATALOG_DETAIL_URL & "/chart"
    Friend Const CATALOG_DETAIL_CHART_OVERVIEW_URL As String = CATALOG_DETAIL_URL & "/chart-overview"
    Friend Const CATALOG_DETAIL_RELEASE_URL As String = CATALOG_DETAIL_URL & "/release"
    Friend Const CATALOG_DETAIL_TRACK_URL As String = CATALOG_DETAIL_URL & "/track"
#End Region

#Region "Most Popular"
    Friend Const CATALOG_MOST_POPULAR_BASE_URL As String = CATALOG_BASE_URL & "/most-popular"
    Friend Const CATALOG_MP_GENRE As String = CATALOG_MOST_POPULAR_BASE_URL & "/genre"
    Friend Const CATALOG_MP_LABEL As String = CATALOG_MOST_POPULAR_BASE_URL & "/label"
    Friend Const CATALOG_MP_ARTIST As String = CATALOG_MOST_POPULAR_BASE_URL & "/artist"
#End Region

#Region "Most Popular Releases"
    Friend Const CATALOG_MOST_POPULAR_RELEASES_BASE_URL As String = CATALOG_MOST_POPULAR_BASE_URL & "-releases"
    Friend Const CATALOG_MPR_GENRE As String = CATALOG_MOST_POPULAR_RELEASES_BASE_URL & "/genre"
    Friend Const CATALOG_MPR_LABEL As String = CATALOG_MOST_POPULAR_RELEASES_BASE_URL & "/label"
#End Region
#End Region

#Region "Identity"
    Friend Const IDENTITY_BASE_URL As String = BASE_URL & "/identity/1"
    Friend Const IDENTITY_BILLING_URL As String = IDENTITY_BASE_URL & "/billing"
    Friend Const IDENTITY_PERSON_URL As String = IDENTITY_BASE_URL & "/person"
    Friend Const IDENTITY_POLL_URL As String = IDENTITY_BASE_URL & "/poll"

#Region "Account"
    Friend Const IDENTITY_ACCOUNT_BASE_URL As String = IDENTITY_BASE_URL & "/account"
    Friend Const IDENTITY_ACCOUNT_REGISTER_URL As String = IDENTITY_BASE_URL & "/register"
    Friend Const IDENTITY_ACCOUNT_RESET_URL As String = IDENTITY_BASE_URL & "/reset"
#End Region

#Region "OAuth"
    Friend Const IDENTITY_OAUTH_BASE_URL As String = IDENTITY_BASE_URL & "/oauth"
    Friend Const IDENTITY_OAUTH_REQUEST_TOKEN_URL As String = IDENTITY_OAUTH_BASE_URL & "/request-token"
    Friend Const IDENTITY_OAUTH_AUTORIZE_URL As String = IDENTITY_OAUTH_BASE_URL & "/authorize"
    Friend Const IDENTITY_OAUTH_ACCESS_TOKEN_URL As String = IDENTITY_OAUTH_BASE_URL & "/access-token"
    Friend Const IDENTITY_OAUTH_DIRECT_ACCESS_TOKEN_URL As String = IDENTITY_OAUTH_BASE_URL & "/direct-access-token"
#End Region
#End Region

#Region "Order"
    Friend Const ORDER_BASE_URL As String = BASE_URL & "/order/1"
    Friend Const ORDER_TRANSACT_URL As String = ORDER_BASE_URL & "/transact"
    Friend Const ORDER_DOWNLOADS_URL As String = ORDER_BASE_URL & "/downloads"
    Friend Const ORDER_PROMO_DOWNLOADS_URL As String = ORDER_BASE_URL & "/promo-downloads"
#End Region

#Region "Dj"
    Friend Const DJ_BASE_URL As String = BASE_URL & "/dj/1"
    Friend Const DJ_PROFILE_URL As String = DJ_BASE_URL & "/profile"
#End Region

#Region "Subscriptions"
    Friend Const SUBSCRIPTIONS_BASE_URL As String = BASE_URL & "/subscriptions/1"
#End Region
#End Region
    ''' <summary>
    ''' Searches the Beatport catalog.
    ''' </summary>
    ''' <param name="searchQuery"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Search(searchQuery As Query) As SearchResponse
        Dim url As String = searchQuery.GetUrl().AbsoluteUri

        Dim response = Me.GetResponse(url)

        Try
            Dim genRes As Catalog.BPOSearchResponse = JsonConvert.DeserializeObject(Of Catalog.BPOSearchResponse)(
                response,
                New Catalog.BeatportObjectJsonCoverter(),
                New Catalog.BeatportObjectListJsonCoverter())

            Return SearchResponse.FromBPObject(genRes)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        Return Nothing
    End Function

    ''' <summary>
    ''' Get genre details.
    ''' </summary>
    ''' <param name="id">Genre ID.</param>
    ''' <returns><see cref="Catalog.Genre">Genre</see></returns>
    ''' <remarks></remarks>
    Public Function GetGenre(id As Integer) As Catalog.Genre
        Dim url As String = String.Format("{0}?id={1}", CATALOG_DETAIL_GENRE_URL, id)
        Dim response = Me.GetResponse(url)

        Try
            Dim genRes As Catalog.BPOGenreSearchResponse = JsonConvert.DeserializeObject(Of Catalog.BPOGenreSearchResponse)(
                response,
                New Catalog.BeatportObjectJsonCoverter(),
                New Catalog.BeatportObjectListJsonCoverter())

            Return Catalog.Genre.FromBPObject(genRes.results.genre)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        Return Nothing
    End Function

    ''' <summary>
    ''' Get artist details.
    ''' </summary>
    ''' <param name="id">Artist ID.</param>
    ''' <returns><see cref="Catalog.Artist">Artist</see></returns>
    ''' <remarks></remarks>
    Public Function GetArtist(id As Integer) As Catalog.Artist
        Dim url As String = String.Format("{0}?id={1}", CATALOG_DETAIL_ARTIST_URL, id)
        Dim response = Me.GetResponse(url)

        Try
            Dim artRes As Catalog.BPOArtistSearchResponse = JsonConvert.DeserializeObject(Of Catalog.BPOArtistSearchResponse)(
                response,
                New Catalog.BeatportObjectJsonCoverter(),
                New Catalog.BeatportObjectListJsonCoverter())

            Return Catalog.Artist.FromBPObject(artRes.results.artist)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        Return Nothing
    End Function

    ''' <summary>
    ''' Get label details.
    ''' </summary>
    ''' <param name="id">Label ID.</param>
    ''' <returns><see cref="Catalog.Label">Labe</see></returns>
    ''' <remarks></remarks>
    Public Function GetLabel(id As Integer) As Catalog.Label
        Dim url As String = String.Format("{0}?id={1}", CATALOG_DETAIL_LABEL_URL, id)
        Dim response = Me.GetResponse(url)

        Try
            Dim labRes As Catalog.BPOLabelSearchResponse = JsonConvert.DeserializeObject(Of Catalog.BPOLabelSearchResponse)(
                response,
                New Catalog.BeatportObjectJsonCoverter(),
                New Catalog.BeatportObjectListJsonCoverter())

            Return Catalog.Label.FromBPObject(labRes.results.label)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        Return Nothing
    End Function

    ''' <summary>
    ''' Get release details.
    ''' </summary>
    ''' <param name="id">Release ID.</param>
    ''' <returns><see cref="Catalog.Release">Release</see></returns>
    ''' <remarks></remarks>
    Public Function GetRelease(id As Integer) As Catalog.Release
        Dim url As String = String.Format("{0}?id={1}", CATALOG_DETAIL_RELEASE_URL, id)
        Dim response = Me.GetResponse(url)

        Try
            Dim relRes As Catalog.BPOReleaseSearchResponse = JsonConvert.DeserializeObject(Of Catalog.BPOReleaseSearchResponse)(
                response,
                New Catalog.BeatportObjectJsonCoverter(),
                New Catalog.BeatportObjectListJsonCoverter())

            Return Catalog.Release.FromBPObject(relRes.results.release)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        Return Nothing
    End Function

    ''' <summary>
    ''' Get track details.
    ''' </summary>
    ''' <param name="id">Track ID.</param>
    ''' <returns><see cref="Catalog.Track">Track</see></returns>
    ''' <remarks></remarks>
    Public Function GetTrack(id As Integer) As Catalog.Track
        Dim url As String = String.Format("{0}?id={1}", CATALOG_DETAIL_TRACK_URL, id)
        Dim response = Me.GetResponse(url)

        Try
            Dim trackRes As Catalog.BPOTrackSearchResponse = JsonConvert.DeserializeObject(Of Catalog.BPOTrackSearchResponse)(
                response,
                New Catalog.BeatportObjectJsonCoverter(),
                New Catalog.BeatportObjectListJsonCoverter())

            Return Catalog.Track.FromBPObject(trackRes.results.track)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        Return Nothing
    End Function

    ''' <summary>
    ''' Get chart details.
    ''' </summary>
    ''' <param name="id">Chart ID.</param>
    ''' <returns><see cref="Catalog.Chart">Chart</see></returns>
    ''' <remarks></remarks>
    Public Function GetChart(id As Integer) As Catalog.Chart
        Dim url As String = String.Format("{0}?id={1}", CATALOG_DETAIL_CHART_URL, id)
        Dim response = Me.GetResponse(url)

        Try
            Dim chartRes As Catalog.BPOChartSearchResponse = JsonConvert.DeserializeObject(Of Catalog.BPOChartSearchResponse)(
                response,
                New Catalog.BeatportObjectJsonCoverter(),
                New Catalog.BeatportObjectListJsonCoverter())

            Return Catalog.Chart.FromBPObject(chartRes.results.chart)
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

        Return Nothing
    End Function

    Private Function GetResponse(url As String) As String
        Using wc As New WebClient()
            Using stream As IO.Stream = wc.OpenRead(url)
                Using reader As New IO.StreamReader(stream)
                    Return reader.ReadToEnd()
                End Using
            End Using
        End Using
    End Function
End Class
